<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/12/27
 * Time: 7:23
 */

namespace app\api\service;

use app\api\model\OrderProduct as OrderProductModel;
use app\api\model\UserAddress as AddressModel;
use app\api\model\Product as ProductModel;
use app\api\model\Order as OrderModel;
use app\lib\Exception\OrderException;
use think\Exception;

class Order
{
    private $uid = 0;
    private $oProducts = [];
    private $products = [];

    public function __construct($uid,$products)
    {
        $this->uid = $uid;
        $this->oProducts = $products;
    }

    public function place()
    {
        $this->products = $this->getProductList();
        $status = $this->getOrderStatus();
        if(!$status['pass']){
            $status['order_id'] = -1;
            return $status;
        }
        $orderSnap = $this->getSnapOrder();
        $orderStatus = $this->makeOrder($orderSnap);
        $orderStatus['pass'] = true;

        return $orderStatus;
    }

    private function getProductList()
    {
        $pid = array();
        foreach($this->oProducts as $oProduct) {
            array_push($pid,$oProduct['product_id']);
        }
        
        $products = ProductModel::all($pid)
            ->visible(['id','price','stock','name','main_img_url'])
            ->toArray();
        // foreach($products as &$product){
        //      $product['price'] = (float)$product['price'];
        // }
        return $products;
    }

    private function getOrderStatus()
    {
        $status = [
            'pass' => true,
            'orderPrice' => 0,
            'orderCount' => 0,
            'statusArray' => []
        ];

        foreach($this->oProducts as $oProduct){
            $pStatus = $this->checkOrderStatus($oProduct['product_id'],$oProduct['count'],$this->products);
            if($pStatus['stock'] == false){
                $status['pass'] = false;
            }
            $status['orderPrice'] += $pStatus['totalPrice'];
            $status['orderCount'] += $pStatus['count'];
            array_push($status['statusArray'],$pStatus);
        }
        return $status;
    }


    private function checkOrderStatus($oProductID,$oProductCount,$products)
    {
        $pIndex = -1;
        $pStatus = [
            'id' => 0,
            'stock' => true,
            'name' => null,
            'totalPrice' => 0,
            'count' => 0
        ];
        for($i = 0;$i<count($products);$i++){
            if($oProductID == $products[$i]['id']){
                $pIndex = $i;
            }
        }
        if($pIndex == -1){
            throw new OrderException();
        }
        $product = $products[$pIndex];
        $pStatus['id'] = $product['id'];
        $pStatus['name'] = $product['name'];
        $pStatus['totalPrice'] = $product['price'] * $oProductCount;
        $pStatus['count'] = $oProductCount;
        $num = $product['stock'] - $oProductCount;
        if(!($product['stock'] - $oProductCount >= 0)){
            $pStatus['stock'] = false;
        }
        return $pStatus;
    }

    private function getSnapOrder()
    {
        $snap = [
            'orderPrice' => 0,
            'orderCount' => 0,
            'status' => [],
            'orderName' => $this->products[0]['name'],
            'orderAddress' => AddressModel::getUserAddress($this->uid)->toArray(),
            'orderImg' => $this->products[0]['main_img_url']
        ];
        if(count($this->products) > 1){
            $snap['orderName'] .= '等';
        }
        
        for($i=0;$i < count($this->products);$i++){
            $oProduct = $this->oProducts[$i];
            $product = $this->products[$i];

            $pStatus = $this->snapProduct($product,$oProduct['count']);
            $snap['orderPrice'] += $pStatus['totalPrice'];
            $snap['orderCount'] += $pStatus['count'];
            array_push($snap['status'],$pStatus);
        }
        return $snap;
    }

    private function snapProduct($product,$count){
        $pStatus = [
            'id' => 0,
            'name' => null,
            'main_img_url' => null,
            'count' => $count,
            'totalPrice' => 0,
            'price' => 0
        ];

        $pStatus['id'] = $product['id'];
        $pStatus['name'] = $product['name'];
        $pStatus['main_img_url'] = $product['main_img_url'];
        $pStatus['price'] = $product['price'];
        $pStatus['count'] = $count;
        $pStatus['totalPrice'] = $count * $product['price'];

        return $pStatus;
    }

    private function makeOrder($snapStatus)
    {
        try{
            $orderNO = $this->createOrderNO();
            
            $model = new OrderModel();
            
            $model->user_id = $this->uid;
            $model->order_no = $orderNO;
            $model->total_price = $snapStatus['orderPrice'];
            $model->total_count = $snapStatus['orderCount'];
            $model->snap_img = $snapStatus['orderImg'];
            $model->snap_name = $snapStatus['orderName'];
            $model->snap_address = json_encode($snapStatus['orderAddress']);
            $model->snap_items = json_encode($snapStatus['status']);

            $model->save();

            $orderID = $model->id;
            $orderCreateTime = $model->create_time;

            foreach($this->oProducts as &$p){
                $p['order_id'] = $orderID;
            }

            $model = new OrderProductModel();
            $model->saveAll($this->oProducts);

            return [
                'order_id' => $orderID,
                'order_on' => $orderNO,
                'create_time' => $orderCreateTime
            ];

        }catch(Exception $e){
            throw $e;
        }
    }

    private function createOrderNO()
    {
        $code = ['A','B','C','D','E','F','G','H','I',
        'J','K','L','M','N','O','P','Q','R','S','T','U',
        'V','W','X','Y','Z'];
        
        return $code[intval(date('Y')) - 2017] . strtoupper(dechex(date('m'))) . date(
            'd') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf(
            '%02d', rand(0, 99));
        
    }
}